﻿//-----------------------------------------------------------------------
// <copyright>
//     Copyright (c) Artur Mustafin. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

#if TRACE
using Parser = Expressions.Compiler.Parser<char>;
#endif

using System;

using Math.Compiler;

namespace Math.Compiler
{
    using System.Collections.Generic;
    using System.IO;
    using Classes;
    using Compiler;
    using Math.Compiler.Expressions;

    public class Core
    {
        private Instructions _instructions = new Instructions();

        private string _errorText;

        /// <summary>
        /// Loads from file.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        public void LoadFromFile(string fileName)
        {
            try
            {
                _instructions.Load(File.ReadAllLines(fileName));
            }
            catch (Exception ex)
            {
                throw new MathException("load error", ex);
            }
        }

        /// <summary>
        /// Saves to file.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        public void SaveToFile(string fileName)
        {
            try
            {
                File.WriteAllLines(fileName, _instructions.Save());
            }
            catch (Exception ex)
            {
                throw new MathException("save error", ex);
            }
        }

        /// <summary>
        /// Loads from lines.
        /// </summary>
        /// <param name="lines">The lines.</param>
        public void LoadFromStrings(IEnumerable<string> lines)
        {
            try
            {
                _instructions.Load(lines);
            }
            catch (Exception ex)
            {
                throw new MathException("load error", ex);
            }
        }

        /// <summary>
        /// Saves to file.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        public IEnumerable<string> SaveToStrings()
        {
            try
            {
                return _instructions.Save();
            }
            catch (Exception ex)
            {
                throw new MathException("save error", ex);
            }
        }

        /// <summary>
        /// Updates the specified variable.
        /// </summary>
        /// <param name="variable">The variable.</param>
        /// <param name="text">The text.</param>
        /// <returns></returns>
        public bool Update(Variable variable, string text)
        {
            try
            {
                _errorText = null;
                if (text == null || string.IsNullOrEmpty(text) || string.IsNullOrWhiteSpace(text))
                {
                    variable.Unsubscribe();
                    variable.MathExpression = null;
                    variable.Text = null;
                    variable.Visit();
                    _instructions.Remove(variable);
                    return true;
                }
                if (variable.Text != text)
                {
                    variable.BeginUpdate();
#if TRACE
                    Parser.ClearTraceLog();
#endif
                    MathExpression expression = Text.Parse(text);
                    if (expression == null)
                    {
                        throw new NotSupportedException("Input string was not in correct format");
                    }
                    if (!variable.Validate(expression))
                    {
                        throw new NotSupportedException("Initialization of the circle referenced instruction is not supported");
                    }
#if TRACE
                    Parser.WriteTraceLog();
#endif
                    _instructions.Update(variable, text, expression);
                }
                variable.EndUpdate();
                return true;
            }
            catch (Exception ex)
            {
                variable.CancelUpdate();
                _errorText = ex.Message;
            }
            return false;
        }

        /// <summary>
        /// Gets the error text.
        /// </summary>
        /// <value>The error text.</value>
        public string ErrorText
        {
            get
            {
                return _errorText;
            }
        }

        /// <summary>
        /// Gets the variablies.
        /// </summary>
        /// <value>The variablies.</value>
        public IEnumerable<Variable> Variablies
        {
            get
            {
                return _instructions.Variables;
            }
        }
    }
}
